package kik.client.whiteboard;

import java.util.Vector;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.XMLParser;
import gwt.canvas.client.Canvas;
import gwt.g2d.client.graphics.ImageLoader;

/**
 * Klasa Image definiuje obiekty graficzne, które reprezentują obrazy.
 * Na obecną chwile GWT potrafi tylko pobierać obrazy z internetu poprzez ścieżkę URL.
 *
 */
public class Image extends Graphics {

	private int x,y,w,h;
	private ImageElement image;
	private String src;
	private boolean create = false;
	
	/**
	 * Podstawowy konstruktor definiujący tylko właściciela i identyfikator.
	 * @param owner	Nazwa właściciela
	 * @param ID	identyfikator obiektu
	 */
	public Image(String owner, String ID) {
		this.setName("Image");
		this.setID(ID);
		this.setOwner(owner);
	}
	
	/**
	 * Konstruktor definiujący obraz.
	 * @param image	Obiekt obrazu.
	 * @param x	Współrzędna x początku obrazu.
	 * @param y	Współrzędna y początku obrazu.
	 * @param board	Płótno, na którym rysowany jest obraz.
	 * @param owner	Nazwa właściciela.
	 * @param ID	Indetyfikator obiektu.
	 * @param src	ścieżka do obrazu.
	 */
	public Image(ImageElement image, int x, int y, Canvas board, String owner, String ID, String src) {
		this.setName("Image");
		this.image = image;
		this.board = board;
		this.x = x;
		this.y = y;
		this.w = image.getWidth();
		this.h = image.getHeight();
		this.setID(ID);
		this.setOwner(owner);
		this.src = src;
		this.create = true;
	}
	
	public boolean belongsTo(int x, int y) {
		if(x >= this.x && x <= this.x+w && y >= this.y && y <= this.y+h) {
			return true;
		}
		return false;
	}

	@Override
	public void draw() {
		if(image!=null) {
			board.drawImage(image, this.x, this.y);
		}
	}

	public void modifyCords(int rx, int ry) {
		this.x = this.x + rx;
		this.y = this.y + ry;
	}

	public Object deserialize(String objStr) {
		Document xml = XMLParser.parse(objStr);
		Element tmp = xml.getDocumentElement();
		if(tmp != null){
			x = Integer.parseInt(tmp.getAttribute("x"));
			y = Integer.parseInt(tmp.getAttribute("y"));
			w = Integer.parseInt(tmp.getAttribute("w"));
			h = Integer.parseInt(tmp.getAttribute("h"));
			create = Boolean.parseBoolean(tmp.getAttribute("create"));
			Tools tool = Tools.valueOf((tmp.getAttribute("Tool")));
			if(create || tool == Tools.NEW) {
				src = tmp.getAttribute("src");
				image = null;
				Vector<String> list = new Vector<String> ();
				list.add(src);
				final Graphics toReDraw = this;
				ImageLoader.loadImages(list, new ImageLoader.CallBack() {
                    public void onImagesLoaded(ImageElement[] imageElements) {
                            setImage(imageElements[0]);
                            toReDraw.draw();
                    }
				});
			}
			this.setOwner(tmp.getAttribute("owner"));
			this.setID(tmp.getAttribute("ID"));
			this.setColor(tmp.getAttribute("color"));
			this.setLocked(Boolean.parseBoolean(tmp.getAttribute("locked")));
		}
		this.draw();
		return this;
	}
	
	public String serialize(String fromID, String tool) {
		Document xml = XMLParser.createDocument();
		Element tmp = xml.createElement("data");
		tmp.setAttribute("type", "WhiteboardChange");
		tmp.setAttribute("graphicType", "Image");
		tmp.setAttribute("x", Integer.toString(x));
		tmp.setAttribute("y", Integer.toString(y));
		tmp.setAttribute("w", Integer.toString(w));
		tmp.setAttribute("h", Integer.toString(h));
		tmp.setAttribute("src", src);
		tmp.setAttribute("create", Boolean.toString(create));
		tmp.setAttribute("owner", getOwner());
		tmp.setAttribute("ID", getID());
		tmp.setAttribute("fromID", fromID);
		tmp.setAttribute("Tool", tool);
		tmp.setAttribute("locked", Boolean.toString(this.isLocked()));
		tmp.setAttribute("color", this.getColor());
		
		xml.appendChild(tmp);
		
		return xml.toString();
	}
	
	/**
	 * Funkcja ustawiająca współrzędną x położenia obrazu. 
	 * @param x_ nowa współrzędna x położenia obrazu.
	 */
	
	public void setX(int x_) {
		x = x_;
	}
	
	/**
	 * Funkcja ustawiająca współrzędną y położenia obrazu.
	 * @param y_ nowa współrzędna y położenia obrazu.
	 */
	
	public void setY(int y_) {
		y = y_;
	}
	
	/**
	 * Funkcja ustalająca nową szerokość obrazu.
	 * @param w_ nowa szerokość obrazu.
	 */
	
	public void setW(int w_) {
		w = w_;
	}
	
	/**
	 * Funkcja ustalająca nową wysokość obrazu.
	 * @param h_ nowa wysokość obrazu.
	 */
	
	public void setH(int h_) {
		h = h_;
	}
	
	/**
	 * Funkcja ustalająca nowy obraz.
	 * @param img nowy obraz.
	 */
	public void setImage(ImageElement img) {
		image = img;
	}
	
	/**
	 * Funkcja zwracająca obecną współrzędną x położenia obrazu.
	 * @return obecna współrzędna x położenia obrazu.
	 */
	
	public int getX() {
		return x;
	}
	
	/**
	 * Funkcja zwracająca obecną współrzędną y położenia obrazu.
	 * @return obecna współrzędna y położenia obrazu.
	 */
	
	public int getY() {
		return y;
	}
	
	/**
	 * Funkcja zwracająca obecną szerokość obrazu.
	 * @return obecna szerokość obrazu.
	 */
	
	public int getW() {
		return w;
	}
	
	/**
	 * Funkcja zwracająca obecną wysokość obrazu.
	 * @return obecna wysokość obrazu.
	 */
	
	public int getH() {
		return h;
	}
	
	/**
	 * Funkcja zwracająca obecny obraz.
	 * @return obecny obraz.
	 */
	
	public ImageElement getImage() {
		return image;
	}
	
	/**
	 * Funkcja ustawiajaca informację o tym, czy obiekt został dopiero stworzony.
	 * @param create true jeżeli obiekt właśnie został stworzony, false w przeciwym wypadku.
	 */
	
	public void setCreate(boolean create){
		this.create = create;
	}
	
	/**
	 * Funkcja zwracająca informację o tym, czy obiekt został dopiero stworzony.
	 * @return true jeżeli obiekt został dopiero stworzony, false w przeciwnym wypadku.
	 */
	public boolean getCreate(){
		return this.create;
	}
	
	/**
	 * @deprecated
	 * Dla poprawnego dzialania serializacji obiektów należy podać infromacje
	 * na temat właściciela obiektu oraz typu zmiany (np dodanie) obiektu.
	 */
	public String serialize() {
		return null;
	}
}
